home *** CD-ROM | disk | FTP | other *** search
/ Cream of the Crop 25 / Cream of the Crop 25.iso / compress / tar321__.zip / SOURCES.ZIP / QICFACE.C < prev    next >
C/C++ Source or Header  |  1994-10-27  |  9KB  |  316 lines

  1. #include <stdio.h>
  2. #include "sysup.h"
  3. #ifdef MSDOS
  4. #include <errno.h>
  5. #include <string.h>
  6. #include <stdlib.h>
  7.  
  8. #include "modern.h"
  9. #include "define.h"
  10. #include "qic02.h"
  11.  
  12. #define MAXLEX 8
  13. #define SKIP_RESET 0x80
  14.  
  15. static int board_type = UNUSED;
  16. static struct init_data id = { UNUSED, UNUSED, UNUSED };
  17. static int no_rewind = FALSE, seek_eod = FALSE, to_skip = 0;
  18. static BYTE cmdset = 0;
  19. static struct { int nqic; BYTE tracks, command; } qiclist[] = {
  20.    { 11,  4,  Q2_QIC11  }, { 24,  9,  Q2_QIC24  },
  21.    { 120, 15, Q2_QIC120 }, { 150, 18, Q2_QIC150 },
  22.    { 300, -1, 0x2A      }, { 2100,-1, 0x2A      },
  23.    { 600, -1, 0x2B      }, { 2200,-1, 0x2B      },
  24. };
  25.  
  26. int qparse(char *s)
  27. {
  28.    static char already[] = "tape format already defined";
  29.    char lex[MAXLEX+1], *errmsg;
  30.    register i, k;
  31.  
  32.    for (i=0; i<MAXLEX && *s && *s!='.'; i++) {
  33.       if (*s == ':' || *s == ';' || *s == ',') goto test_name;
  34.       lex[i] = *s++;
  35.    }
  36.    return FALSE;
  37. test_name:
  38.    lex[i] = '\0';
  39.    if ((board_type=streamer('?', lex, 0)) < 0) return FALSE;
  40.  
  41.    id.base_address = UNUSED;
  42.    id.dma_number   = UNUSED;
  43.    id.irq_number   = UNUSED;
  44.    no_rewind       = FALSE;
  45.    seek_eod        = FALSE;
  46.    to_skip         = 0;
  47.  
  48.    while (*++s) {
  49.       for (i=0; i<=MAXLEX; ++i, s++) {
  50.          if      (*s >= 'A' && *s <= 'Z') lex[i] = *s | ('z'^'Z');
  51.          else if (*s >= 'a' && *s <= 'z') lex[i] = *s;
  52.          else break;
  53.       }
  54.       if (i < 1 || i > MAXLEX) {
  55.          errmsg = "device parameter error"; goto error;
  56.       }
  57.       lex[i] = '\0'; /* for diagnostic printing */
  58.       if (!strncmp("norewind", lex, i)) {
  59.          if (seek_eod || to_skip) goto excl;
  60.          no_rewind = TRUE;
  61.       } else if (!strncmp("add", lex, i)) {
  62.          if (to_skip || no_rewind) goto excl;
  63.          seek_eod = TRUE;
  64.       } else if (!strncmp("qic", lex, i)) {
  65.          if (cmdset) {
  66.             errmsg = already; goto error;
  67.          }
  68.          if (*s == '-') {
  69.             ++s;
  70.          } else {
  71.             if (*s == ':') ++s;
  72.             if (*s == '=') ++s;
  73.          }
  74.          if (*s >= '1' && *s <= '9') {
  75.             k = 0; i = 0;
  76.             do {
  77.                k = (*s++ - '0') + 10*k;
  78.             } while (++i < 5 && *s >= '0' && *s <= '9');
  79.             if (i < 5) {
  80.                for (i=0; i<dimof(qiclist); i++) {
  81.                   if (qiclist[i].nqic == k) {
  82.                      cmdset = qiclist[i].command; break;
  83.                   }
  84.                }
  85.             }
  86.          }
  87.          if (!cmdset) {
  88.             errmsg = "invalid QIC number"; goto error;
  89.          }
  90.       } else {
  91.          if (*s == ':') ++s;
  92.          if (*s == '=') ++s;
  93.          if (strncmp("base", lex, i) == 0) {
  94.             for (id.base_address=0, i=0; i<5; ++i, s++) {
  95.                register j = '0';
  96.                if      (*s>='A' && *s<='F') j = 'A' - 10;
  97.                else if (*s>='a' && *s<='f') j = 'a' - 10;
  98.                else if (*s <'0' || *s >'9') break;
  99.                id.base_address = (id.base_address << 4) | (*s - j);
  100.             }
  101.             if (i<1 || i>4) {
  102.                errmsg = "invalid base address"; goto error;
  103.             }
  104.             if (*s == 'h' || *s == 'H') ++s;
  105.          } else if (strncmp("dma", lex, i) == 0) {
  106.             if (*s<'0' || *s>'7') {
  107.                errmsg = "invalid DMA channel number"; goto error;
  108.             }
  109.             id.dma_number = *s++ & 7;
  110.          } else if (strncmp("irq", lex, i) == 0) {
  111.             for (id.irq_number=0, i=0; i<3 && *s>='0' && *s<='9'; ++i, s++) {
  112.                id.irq_number = 10*id.irq_number + *s - '0';
  113.             }
  114.             if (i<1 || i>2 || id.irq_number > 15) {
  115.                errmsg = "invalid IRQ number"; goto error;
  116.             }
  117.          } else if (strncmp("tracks", lex, i) == 0) {
  118.             if (cmdset) {
  119.                errmsg = already; goto error;
  120.             }
  121.             for (k=0, i=0; i<3 && *s>='0' && *s<='9'; ++i, s++) {
  122.                k = (*s - '0') + 10*k;
  123.             }
  124.             if (i > 0 && i < 3) {
  125.                for (i=0; i<dimof(qiclist); i++) {
  126.                   if (qiclist[i].tracks == k) {
  127.                      cmdset = qiclist[i].command; break;
  128.                   }
  129.                }
  130.             }
  131.             if (!cmdset) {
  132.                errmsg = "invalid number of tracks"; goto error;
  133.             }
  134.          } else if (!strncmp("skip", lex, i)) {
  135.             if (seek_eod || no_rewind) goto excl;
  136.             for (to_skip=0, i=0; i<5 && *s>='0' && *s<='9'; ++i, s++) {
  137.                to_skip = (*s - '0') + 10*to_skip;
  138.             }
  139.          } else {
  140.             (void)fprintf(stderr,"Tar: unknown parameter \'%s\'\n",lex);
  141.             return ERROR;
  142.          }
  143.       }
  144.       if (*s == '\0') break;
  145.       if (*s != ',' && *s != ':' && *s != '.') {
  146.          (void)fprintf(stderr,"Tar: invalid character after \'%s\'\n",lex);
  147.          return ERROR;
  148.       }
  149.    }
  150.    if (id.base_address == UNUSED) {
  151.       errmsg = "base address must be specified"; goto error;
  152.    }
  153.    if (!cblock) cblock = 1;
  154.    return TRUE;
  155. excl:
  156.    errmsg = "\'add\', \'skip\' and \'norewind\' are mutually exclusive";
  157. error:
  158.    (void)fprintf(stderr,"Tar: %s\n", errmsg);
  159.    return ERROR;
  160. }
  161.  
  162. static void qerror(int k)
  163. {
  164.    if (k < 0) {
  165.       (void)fprintf(stderr, "Tar: %s\n", strerror(errno));
  166.    } else if (k < qic02_nerr) {
  167.       (void)fprintf(stderr, "Tar: %s\n", qic02_errlist[k]);
  168.    } else {
  169.       (void)fprintf(stderr, "Tar: error #%d\n", k);
  170.    }
  171. }
  172.  
  173. int qbegin(void)
  174. {
  175.    register k;
  176.  
  177.    if (no_rewind) board_type |= SKIP_RESET;
  178.    if ((k=streamer('o', &id, board_type)) != 0) {
  179.       if (k != CTE_FAULT || errno != EINVDAT) goto error;
  180.       (void)fprintf(stderr, "Tar: unsupported hardware configuration\n");
  181.       return k;
  182.    }
  183.    if (setdrive) {
  184.       if ((k=streamer('i',NULL,(1<<ndrive)&15/*|Q2_SELECT*/))!=0) goto error;
  185.    }
  186.    if (!no_rewind) {
  187. #if 0
  188.       if ((k=c_flag ? streamer('i',NULL,Q2_ERASE) : streamer('n',NULL,0))!=0)
  189.          goto error;
  190. #else
  191.       if ((k=streamer('n', NULL, 0)) != 0) goto error;
  192.       if (c_flag && !(seek_eod || to_skip)) {
  193.          if ((k=streamer('i', NULL, Q2_ERASE)) != 0 ||
  194.              (k=streamer('n', NULL, 0)) != 0) goto error;
  195.       }
  196. #endif
  197.       if (cmdset) {/* select tape format */
  198.          if ((k=streamer('i', NULL, cmdset)) != 0) goto error;
  199.       }
  200.       if (to_skip) {
  201.          if ((k=streamer('f', NULL, to_skip)) != 0) goto error;
  202.       } else if (seek_eod) {
  203.          if ((k=streamer('i', NULL, Q2_EOD)) != 0) goto error;
  204.          if ((k=streamer('t', NULL, 0)) != 0) {
  205.             if (k!=Q2E_ERM && k!=Q2E_NDT) goto error;
  206.             k = 0;
  207.          }
  208.       }
  209.    }
  210.    return 0;
  211. error:
  212.    qerror(k);
  213.    return k;
  214. }
  215.  
  216. void qend(void)
  217. {
  218.    if        (a_flag)   streamer('d',NULL,0);
  219.    else if (!no_rewind) streamer('n',NULL,0);
  220.    streamer('c',NULL,0);
  221. }
  222.  
  223. static void ioerror(unsigned mask)
  224. {
  225.    register k;
  226.    struct qic02_word_status s;
  227.    extern int ct_errbit(unsigned);
  228.  
  229.    k = streamer('t', &s, 0);
  230.    if (k >= 0 && k <= CTE_BUSY) {
  231.       k = ct_errbit(mask & s.status);
  232.    }
  233.    qerror(k);
  234. }
  235.  
  236. /* Interface routines */
  237. int qread(char *buf, register int n)
  238. {
  239.    if (n & (BLKSIZE-1)) return -1;
  240.    if (streamer('r', buf, n) != n) {
  241.       ioerror(~(Q2E_BOM|Q2E_WRP));
  242.       return -1;
  243.    }
  244.    return n;
  245. }
  246.  
  247. int qwrite(char *buf, register int n)
  248. {
  249.    n = (BLKSIZE-1 + n) & ~(BLKSIZE-1);
  250.    if (streamer('w', buf, n) != n) {
  251.       ioerror(~Q2E_BOM);
  252.       return -1;
  253.    }
  254.    return n;
  255. }
  256.  
  257. int qback(n)
  258. register n;
  259. {
  260.    register j, k;
  261.    for (j=(n+cblock-1)/cblock; j; j--)
  262.       if ((k=streamer('i',NULL,Q2_REVERSE)) != 0) {
  263.          qerror(k); return -1;
  264.       }
  265.    return n;
  266. }
  267. #endif
  268.  
  269. char *getbuf(length)
  270. int length;
  271. {
  272.    register char *ptr;
  273. #ifdef MSDOS
  274.    int dw; /* size of DMA word */
  275.  
  276.    dw = id.dma_number & ~7 ? 0 : 1 + (id.dma_number >> 2);
  277.    ptr = malloc(length);
  278.    if (!ptr) {
  279.       (void)fprintf(stderr, "Tar: not enough memory\n");
  280.    } else if (dw > 0) {
  281.       long a; register s;
  282.  
  283.       a = ptr2abs(ptr);
  284.       s = dw + 15; /* shift factor to get DMA page number */
  285.       /* Compare DMA pages */
  286.       if ((a >> s) != ((a+length-1) >> s)) {
  287.       /* Attempt to get DMA page-aligned buffer assumes: */
  288.       /*  - length is not greater than half of DMA page; */
  289.       /*  - malloc() heap is unfragmented.               */
  290.          register void *tmp;
  291.  
  292.          tmp = ptr; ptr = malloc(length); free(tmp);
  293.          if (!ptr) {
  294.             (void)fprintf(stderr, "Tar: no memory to align buffer\n");
  295.             return (void *)0;
  296.          }
  297.          a = ptr2abs(ptr);
  298.          if ((a >> s) != ((a+length-1) >> s)) {
  299.             (void)fprintf(stderr, "Tar: fail to align buffer\n");
  300.             free(ptr); return (void *)0;
  301.          }
  302.       }
  303.       if (a & (dw - 1)) {
  304.          (void)fprintf(stderr, "Tar: DMA buffer is not word-aligned\n");
  305.          free(ptr); return (void *)0;
  306.       }
  307.    }
  308.    return ptr;
  309. #else
  310.    extern char *malloc();
  311.    ptr = malloc(length);
  312.    if (!ptr) (void)fprintf(stderr, "Tar: not enough memory\n");
  313.    return ptr;
  314. #endif
  315. }
  316.